﻿using System;
using iTeamyou.LTS.Core.Models;
using iTeamyou.LTS.Core.Utils;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace iTeamyou.LTS.Core.Services
{
	public class BatchService : IDataService<Batch, BatchLicense>
	{
        public MainDBContext _dbContext;
        private readonly ILogger<Batch> _logger;
        private Comparator _comparator;
        private BatchAttachmentService _attachmentService;
        public SharedService _sharedService = new SharedService();
        public ProductService _productService;

        public BatchService()
        {
            _dbContext ??= new MainDBContext();
        }

        public BatchService(string connectionString)
        {
            _dbContext = new MainDBContext(new DbContextOptionsBuilder<MainDBContext>().UseMySql(connectionString, new MySqlServerVersion(new Version())).Options);
        }

        public BatchService(MainDBContext dbContext, ILogger<Batch> logger, BatchAttachmentService attachmentService, ProductService productService)
		{
            _dbContext = dbContext;
            _logger = logger;
            _comparator = new Comparator();
            _attachmentService = attachmentService;
            _productService = productService;
        }

        public int Delete(IEnumerable<Batch> batches)
        {
            _dbContext.Batches.RemoveRange(batches);
            return _dbContext.SaveChanges();
        }

        public Batch Get(string id)
        {
            return _dbContext.Batches.AsNoTracking().FirstOrDefault(s => s.Id == id);
        }

        public List<Batch> GetByNumber(string number)
        {
            return _dbContext.Batches.AsNoTracking().Where(s => s.Number == number || s.OrderNumber == number).ToList();
        }

        public BatchLicense GetLicenseByLId(string lid)
        {
            return _dbContext.BatchLicenses.AsNoTracking().Where(s => s.LId == lid).FirstOrDefault();
        }

        public List<Batch> GetByID(string bid)
        {
            return _dbContext.Batches.AsNoTracking().Where(s => s.BId == bid).ToList();
        }

        public List<Batch> GetList()
        {
            var list = _dbContext.Batches.AsNoTracking().OrderByDescending(s => s.LastModifiedOn).ToList();
            //if (list.Count > 0)
            //{
            //    foreach(var batch in list)
            //    {
            //        batch.BatchLicenses = GetLicensesById(batch.Id);
            //    }
            //}

            return list;
        }

        public List<ExportBatch> GetExport()
        {
            var result = new List<ExportBatch>();
            var list = _dbContext.Batches.AsNoTracking().OrderByDescending(s => s.LastModifiedOn).ToList();
            if (list.Count > 0)
            {
                foreach (var batch in list)
                {
                    var supplier = _dbContext.Suppliers.AsNoTracking().FirstOrDefault(p => p.Id == batch.SupplierId);
                    //var product = _dbContext.Products.AsNoTracking().FirstOrDefault(p => p.Id == batch.ProductId);
                    var product = _productService.Get(batch.ProductId);
                    var export = new ExportBatch()
                    {
                        Id = batch.BId,
                        //ProductId = batch.ProductSKU,
                        //ProductUPC = batch.ProductUPC,
                        //ProductName = batch.ProductName,
                        ProductId = product?.PId,
                        ProductUPC = product?.UPC,
                        ProductName = product?.Name,
                        Quantity = batch.Quantity,
                        StoreId = batch.StoreId,
                        StoreName = batch.StoreName,
                        SupplierName = supplier != null ? supplier.Name : batch.SupplierName,
                        SupplierId = supplier?.SId,
                        SupplierContact = supplier?.ContactNumber,
                        OrderNumber = batch.OrderNumber,
                        Number = batch.Number,
                        EntryDatetime = batch.EntryDatetime,
                        WarehouseNumber = batch.WarehouseNumber,
                        DateDue = batch.DateDue,
                        Specification = product?.Specification,
                        Department = _productService.GetProductDepartment(product?.SectionId)?.Description,
                        ProducedDate = batch.ProducedDate,
                        ValidDate = ((DateTime)batch.DateDue - (DateTime)batch.ProducedDate).Days
                    };

                    var licenses = GetLicensesById(batch.Id);
                    var urlList = new List<string>();
                    if (licenses.Count > 0)
                    {
                        foreach (var license in licenses)
                        {
                            var attachment = _attachmentService.GetList(license.Id, true).FirstOrDefault();
                            if (attachment != null)
                                urlList.Add(attachment.URL);
                            var otherAttachment = _attachmentService.GetList(license.Id, false);
                            if (otherAttachment != null && otherAttachment.Any())
                                otherAttachment.ForEach(o => urlList.Add(o.URL));
                        }
                    }
                    export.BatchLicenseUrl = urlList;
                    result.Add(export);
                }
            }
            return result;
        }

        public List<ExportBatch> GetExport(List<Batch> batches)
        {
            var result = new List<ExportBatch>();
            if (batches.Count > 0)
            {
                foreach (var batch in batches)
                {
                    var supplier = _dbContext.Suppliers.AsNoTracking().FirstOrDefault(p => p.Id == batch.SupplierId);
                    var product = _productService.Get(batch.ProductId);
                    var export = new ExportBatch()
                    {
                        Id = batch.BId,
                        //ProductId = batch.ProductSKU,
                        //ProductUPC = batch.ProductUPC,
                        //ProductName = batch.ProductName,
                        ProductId = product?.PId,
                        ProductUPC = product?.UPC,
                        ProductName = product?.Name,
                        Quantity = batch.Quantity,
                        StoreId = batch.StoreId,
                        StoreName = batch.StoreName,
                        SupplierName = supplier != null ? supplier.Name : batch.SupplierName,
                        SupplierId = supplier?.SId,
                        SupplierContact = supplier?.ContactNumber,
                        OrderNumber = batch.OrderNumber,
                        Number = batch.Number,
                        EntryDatetime = batch.EntryDatetime,
                        WarehouseNumber = batch.WarehouseNumber,
                        DateDue = batch.DateDue,
                        Specification = product?.Specification,
                        Department = _productService.GetProductDepartment(product?.SectionId)?.Description,
                        ProducedDate = batch.ProducedDate,
                        ValidDate = ((DateTime)batch.DateDue - (DateTime)batch.ProducedDate).Days
                };

                    var licenses = GetLicensesById(batch.Id);
                    var urlList = new List<string>();
                    if (licenses.Count > 0)
                    {
                        foreach (var license in licenses)
                        {
                            var attachment = _attachmentService.GetList(license.Id, true).FirstOrDefault();
                            if (attachment != null)
                                urlList.Add(attachment.URL);
                            var otherAttachment = _attachmentService.GetList(license.Id, false);
                            if (otherAttachment != null && otherAttachment.Any())
                                otherAttachment.ForEach(o => urlList.Add(o.URL));
                        }
                    }
                    export.BatchLicenseUrl = urlList;
                    result.Add(export);
                }
            }
            return result;
        }

        public void Save(Batch batch)
        {
            var exists = _dbContext.Batches.Where(g => g.Id == batch.Id).FirstOrDefault();
            if (exists == null)
            {
                if (batch.CreatedOn == null)
                    batch.CreatedOn = DateTime.Now;
                _dbContext.Add(batch);
            }
            else
            {
                exists.Number = batch.Number;
                exists.Quantity = batch.Quantity;
                exists.StoreId = batch.StoreId;
                exists.StoreName = batch.StoreName;
                exists.SupplierId = batch.SupplierId;
                //exists.ProductId = batch.ProductId;
                exists.EntryDatetime = batch.EntryDatetime;
                exists.WarehouseNumber = batch.WarehouseNumber;
                exists.OrderNumber = batch.OrderNumber;
                exists.ValidDate = batch.ValidDate;
                exists.DateDue = batch.DateDue;
                exists.ProducedDate = batch.ProducedDate;
                exists.LastModifiedBy = batch.LastModifiedBy;
                exists.LastModifiedOn = batch.LastModifiedOn;
                //exists.BatchLicenses = batch.BatchLicenses;
                //if (batch.BatchLicenses != null && batch.BatchLicenses.Count() > 0)
                exists.LicenseNum = _dbContext.BatchLicenses.Where(s => s.BatchId == batch.Id && s.IsPublish == true).Count();
                exists.BatchLicenses = batch.BatchLicenses;
                //SaveLicense(batch.Id, batch.BatchLicenses, batch.LastModifiedBy);
                SaveLicense(exists);
            }
            _dbContext.SaveChanges();
        }
        //新增批量保存
        public void BatchSave(List<Batch> batchesToInsert)
        {
            Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 开始批量更新，共 {batchesToInsert.Count} 条入库管理数据。");
            if (batchesToInsert == null || !batchesToInsert.Any()) return;

            // 提取所有需要处理的 Batch IDs
            var batchIds = batchesToInsert.Select(b => b.Id).ToList();

            // 查询数据库中已存在的 Batch 记录
            var existingBatches = _dbContext.Batches.Where(b => batchIds.Contains(b.Id)).ToList();

            // 构建一个字典以便快速查找现有记录
            var existingBatchesDict = existingBatches.ToDictionary(b => b.Id, b => b);

            foreach (var batch in batchesToInsert)
            {
                if (existingBatchesDict.TryGetValue(batch.Id, out var existingBatch))
                {
                    // 更新现有记录
                    existingBatch.Number = batch.Number;
                    existingBatch.Quantity = batch.Quantity;
                    existingBatch.StoreId = batch.StoreId;
                    existingBatch.StoreName = batch.StoreName;
                    existingBatch.SupplierId = batch.SupplierId;
                    existingBatch.EntryDatetime = batch.EntryDatetime;
                    existingBatch.WarehouseNumber = batch.WarehouseNumber;
                    existingBatch.OrderNumber = batch.OrderNumber;
                    existingBatch.ValidDate = batch.ValidDate;
                    existingBatch.DateDue = batch.DateDue;
                    existingBatch.ProducedDate = batch.ProducedDate;
                    existingBatch.LastModifiedBy = batch.LastModifiedBy;
                    existingBatch.LastModifiedOn = batch.LastModifiedOn;
                    existingBatch.LicenseNum = _dbContext.BatchLicenses.Count(s => s.BatchId == batch.Id && s.IsPublish == true);
                    existingBatch.BatchLicenses = batch.BatchLicenses;
                    SaveLicense(existingBatch);
                }
                else
                {
                    if (batch.CreatedOn == null)
                    {
                        batch.CreatedOn = DateTime.Now;
                    }
                    _dbContext.Add(batch);
                }
            }
            _dbContext.SaveChanges();
        }

        public List<BatchLicense> GetLicenses(List<BatchLicense>? licenses = null)
        {
            var result = new List<BatchLicense>();
            if (licenses != null && licenses.Any())
                result = licenses;
            else
                result = _dbContext.BatchLicenses.AsNoTracking().Where(l => l.IsPublish == true).ToList();

            foreach (var license in result)
            {
                if (license.ValidToDate != null)
                    license.RemainingDays = ((DateTime)license.ValidToDate - DateTime.Now).Days;

                //var attachment = _attachmentService.GetList(license.Id, true).FirstOrDefault();
                //var licenseList = new List<string>();
                //if (attachment != null)
                //    licenseList.Add(attachment.URL);
                //var otherAttachment = _attachmentService.GetList(license.Id, false);
                //if (otherAttachment != null && otherAttachment.Any())
                //    otherAttachment.ForEach(o => licenseList.Add(o.URL));

                //license.AttachmentURL = licenseList;
            }
            return result;
        }

        public List<BatchLicense> GetLicensesExport(List<BatchLicense>? licenses = null)
        {
            var result = new List<BatchLicense>();
            if (licenses != null && licenses.Any())
                result = licenses;
            else
                result = _dbContext.BatchLicenses.AsNoTracking().Where(l => l.IsPublish == true).ToList();

            foreach (var license in result)
            {
                if (license.ValidToDate != null)
                    license.RemainingDays = ((DateTime)license.ValidToDate - DateTime.Now).Days;

                var attachment = _attachmentService.GetList(license.Id, true).FirstOrDefault();
                var licenseList = new List<string>();
                if (attachment != null)
                    licenseList.Add(attachment.URL);
                var otherAttachment = _attachmentService.GetList(license.Id, false);
                if (otherAttachment != null && otherAttachment.Any())
                    otherAttachment.ForEach(o => licenseList.Add(o.URL));

                license.AttachmentURL = licenseList;
            }
            return result;
        }

        public int GetLicenseCount()
        {
            return _dbContext.BatchLicenses.Count(l => l.IsPublish == true);
        }

        public List<BatchLicense> GetLicensesById(string id)
        {
            return _dbContext.BatchLicenses.AsNoTracking().Where(s => s.BatchId == id && s.IsPublish == true).ToList();
        }

        public List<LicenseType> GetLicenseType(string type = "")
        {
            if (string.IsNullOrEmpty(type))
                return _dbContext.LicenseTypes.AsNoTracking().ToList();
            return _dbContext.LicenseTypes.AsNoTracking().Where(l => l.Module == type).ToList();
        }

        private void SaveLicense(Batch batch)
        {
            var licenses = batch.BatchLicenses;
            var id = batch.Id;
            var userId = batch.LastModifiedBy;

            var exists = _dbContext.BatchLicenses.AsNoTracking().Where(s => s.BatchId == id && s.IsPublish == true).OrderBy(s => s.Id).ToList();
            var licensesCompare = licenses.OrderBy(l => l.Id).ToList();
            if (_comparator.DifferenceComparison(exists, licensesCompare))
            {
                //发起流程
                var currentTbId = "fd_3c7343ed25a0e8";
                var historyTbId = "fd_3c7344bbcb4a6c";
                var flowService = new EKPFlowService();
                var formValues = new string("{\"fd_3c73440309699e\":\"" + batch.OrderNumber + "\", \"fd_3c734404052200\":\"" + batch.Number + "\",");
                var tbValue1 = $"\"{currentTbId}.fd_3c7344a1863166\":[";
                var tbValue2 = $"\"{currentTbId}.fd_3c7491d44ed0da\":[";
                var tbValue3 = $"\"{currentTbId}.fd_3c7491d84aabe6\":[";
                var tbValue4 = $"\"{currentTbId}.fd_3c7344a53921c2\":[";
                var tbValue5 = $"\"{currentTbId}.fd_3c7344a7ced6b2\":[";
                var tbValue6 = $"\"{currentTbId}.fd_3c7344a67ef9e8\":[";

                var tbHistoryValue1 = $"\"{historyTbId}.fd_3c7344e5124b46\":[";
                var tbHistoryValue2 = $"\"{historyTbId}.fd_3c749202cd5272\":[";
                var tbHistoryValue3 = $"\"{historyTbId}.fd_3c749204297b04\":[";
                var tbHistoryValue4 = $"\"{historyTbId}.fd_3c7344e8f4f4b6\":[";
                var tbHistoryValue5 = $"\"{historyTbId}.fd_3c7344ea331368\":[";

                if (exists != null && exists.Any())
                {
                    exists.ForEach(e =>
                    {
                        var attachmentURL = string.Empty;
                        var attachment = e.Attachments?.FirstOrDefault(l => l.IsMain == true);
                        if (attachment != null)
                            attachmentURL = attachment.URL;

                        tbHistoryValue1 += "\"" + GetLicenseTypeName(e.Type, "batch") + "\",";
                        tbHistoryValue2 += "\"" + ((DateTime)e.ValidFromDate).ToString("yyyy-MM-dd") + "\",";
                        tbHistoryValue3 += "\"" + ((DateTime)e.ValidToDate).ToString("yyyy-MM-dd") + "\",";
                        tbHistoryValue4 += "\"" + e.LId + "\",";
                        tbHistoryValue5 += "\"" + attachmentURL + "\",";
                    });

                    tbHistoryValue1 = tbHistoryValue1.Remove(tbHistoryValue1.LastIndexOf(","), 1) + "],";
                    tbHistoryValue2 = tbHistoryValue2.Remove(tbHistoryValue2.LastIndexOf(","), 1) + "],";
                    tbHistoryValue3 = tbHistoryValue3.Remove(tbHistoryValue3.LastIndexOf(","), 1) + "],";
                    tbHistoryValue4 = tbHistoryValue4.Remove(tbHistoryValue4.LastIndexOf(","), 1) + "],";
                    tbHistoryValue5 = tbHistoryValue5.Remove(tbHistoryValue5.LastIndexOf(","), 1) + "],";
                    formValues += tbHistoryValue1 + tbHistoryValue2 + tbHistoryValue3 + tbHistoryValue4 + tbHistoryValue5;
                }

                if (licenses != null && licenses.Any())
                {
                    licenses.ForEach(license =>
                    {
                        var existLicense = exists.FirstOrDefault(l => l.Id == license.Id);
                        if (string.IsNullOrEmpty(license.Id) || _comparator.DifferenceEntityComparison(existLicense, license))
                        {
                            if (exists.Any(e => e.Id == license.Id) && license.OperationType != LicenseOp.Delete)
                                license.OperationType = LicenseOp.Modify;
                            else if (license.OperationType != LicenseOp.Delete)
                                license.OperationType = LicenseOp.Add;

                            if (string.IsNullOrEmpty(license.CreatedBy))
                                license.CreatedBy = userId;

                            license.Id = Guid.NewGuid().ToString("N");
                            license.IsPublish = false;

                            license.Attachments?.ForEach(a =>
                            {
                                a.Id = Guid.NewGuid().ToString("N");
                                a.LicenseId = license.Id;
                                _dbContext.BatchLicenseAttachments.Add(a);
                            });

                            var opTypeString = "";
                            if (license.OperationType == LicenseOp.Add)
                                opTypeString = "新增";
                            else if (license.OperationType == LicenseOp.Modify)
                                opTypeString = "修改";
                            else if (license.OperationType == LicenseOp.Delete)
                                opTypeString = "删除";

                            var attachmentURL = string.Empty;
                            var attachment = license.Attachments?.FirstOrDefault(l => l.IsMain == true);
                            if (attachment != null)
                                attachmentURL = attachment.URL;

                            tbValue1 += "\"" + GetLicenseTypeName(license.Type, "batch") + "\",";
                            tbValue2 += "\"" + ((DateTime)license.ValidFromDate).ToString("yyyy-MM-dd") + "\",";
                            tbValue3 += "\"" + ((DateTime)license.ValidToDate).ToString("yyyy-MM-dd") + "\",";
                            tbValue4 += "\"" + license.LId + "\",";
                            tbValue5 += "\"" + opTypeString + "\",";
                            tbValue6 += "\"" + attachmentURL + "\",";

                            license.Attachments = new List<BatchLicenseAttachment>();
                        }
                    });

                    tbValue1 = tbValue1.Remove(tbValue1.LastIndexOf(","), 1) + "],";
                    tbValue2 = tbValue2.Remove(tbValue2.LastIndexOf(","), 1) + "],";
                    tbValue3 = tbValue3.Remove(tbValue3.LastIndexOf(","), 1) + "],";
                    tbValue4 = tbValue4.Remove(tbValue4.LastIndexOf(","), 1) + "],";
                    tbValue5 = tbValue5.Remove(tbValue5.LastIndexOf(","), 1) + "],";
                    tbValue6 = tbValue6.Remove(tbValue6.LastIndexOf(","), 1) + "]";
                    formValues += tbValue1 + tbValue2 + tbValue3 + tbValue4 + tbValue5 + tbValue6 + "}";
                    var flowId = flowService.AddReview(_sharedService.GetConfig("EKPBatchLicenseTemplateId"), "批次证照更新", userId, formValues);

                    licenses.ForEach(l => l.RefFlowId = flowId);
                    _dbContext.BatchLicenses.AddRange(licenses);
                }
                //else //todo: 观察
                //    _dbContext.ProductLicenses.RemoveRange(exists);

                _dbContext.SaveChanges();
            }
        }

        //private void SaveLicense(string id, List<BatchLicense> licenses, string userId)
        //{
        //    var exists = _dbContext.BatchLicenses.Where(s => s.BatchId == id && s.IsPublish == true);
        //    if (_comparator.DifferenceComparison(exists.OrderBy(e => e.Id).ToList(), licenses.OrderBy(l => l.Id).ToList()))
        //    {
        //        if (licenses != null && licenses.Count > 0)
        //        {
        //            //发起流程
        //            var flowService = new EKPFlowService();
        //            var flowId = flowService.AddReview(_sharedService.GetConfig("EKPBatchLicenseTemplateId"), "批次证照更新", userId);

        //            licenses.ForEach(l =>
        //            {
        //                if (string.IsNullOrEmpty(l.CreatedBy))
        //                    l.CreatedBy = userId;

        //                l.Id = Guid.NewGuid().ToString("N");
        //                l.IsPublish = false;
        //                l.RefFlowId = flowId;

        //                if (l.Attachments != null)
        //                {
        //                    l.Attachments.ForEach(a =>
        //                    {
        //                        a.Id = Guid.NewGuid().ToString("N");
        //                        a.LicenseId = l.Id;
        //                        _dbContext.BatchLicenseAttachments.Add(a);
        //                    });
        //                    l.Attachments = new List<BatchLicenseAttachment>();
        //                }

        //                if (exists.Any(e => e.Id == l.Id) && l.OperationType != LicenseOp.Delete)
        //                    l.OperationType = LicenseOp.Modify;
        //                else if(l.OperationType != LicenseOp.Delete)
        //                    l.OperationType = LicenseOp.Add;
        //            });

        //            _dbContext.BatchLicenses.AddRange(licenses);
        //        }
        //        //else
        //        //    _dbContext.BatchLicenses.RemoveRange(exists);

        //        _dbContext.SaveChanges();
        //    }
        //}

        public void UploadLicense(BatchLicense license)
        {
            _dbContext.BatchLicenses.Add(license);
            _dbContext.SaveChanges();
        }

        public void LicenseStatistics()
        {
            var batches = GetList();
            if (batches.Any())
            {
                foreach (var batch in batches)
                {
                    var licenses = GetLicensesById(batch.Id);
                    if (licenses.Any())
                    {
                        var update = _dbContext.Batches.Where(p => p.Id == batch.Id).FirstOrDefault();
                        update.LicenseNum = licenses.Count();
                        _dbContext.SaveChanges();
                    }
                }
            }
        }

        private string GetLicenseTypeName(string id, string module)
        {
            var licenseTypes = GetLicenseType();
            if (licenseTypes != null && licenseTypes.Any())
            {
                var licenseType = licenseTypes.FirstOrDefault(predicate: l => l.TypeId == id && l.Module == module);
                if (licenseType != null)
                    return licenseType.TypeName;
            }
            return string.Empty;
        }
    }
}

